from InstructionAnalysis import InstructionAnalysis


class DynamicScheduling:

    instructionAnalysis = InstructionAnalysis()

    instructions = []
    instructionsSplitList = []
    graphDAG = []
    stallTimes = []

    def __init__(self):
        # print(self.instructionAnalysis.regName)
        # print(self.instructionAnalysis.regABIName)
        pass

    def readCode(self, filename):
        self.instructions = []
        self.instructionsSplitList = []
        """

        Args:
            filename:汇编文件

        Returns:没有返回，设置instructions和instructionsSplitList

        """
        tempIstList = []
        for i in open(filename):
            i = i.strip()
            tempIstList.append(i)

        tempIstList = [ist for ist in tempIstList if ist != ""]

        for i in range(1, len(tempIstList)):
            if ":" in tempIstList[i]:
                continue
            elif ":" in tempIstList[i-1]:
                self.instructions.append(tempIstList[i-1] + tempIstList[i])
            else:
                self.instructions.append(tempIstList[i])

        for ist in self.instructions:
            self.instructionsSplitList.append([i for i in self.instructionAnalysis.instructionSplit(ist) if i != ""])

        for i in range(0, len(self.instructions)):
            self.graphDAG.append([0 for i in self.instructions])
            self.stallTimes.append([0 for i in self.instructions])

    def BuildDAG(self, instructionsSplitList):
        for i in range(0, len(instructionsSplitList)):
            for j in range(i, len(instructionsSplitList)):

                opt_forword = ''
                opt_backword = ''
                for opt in self.instructionAnalysis.instructionOpcode:
                    if opt in self.instructions[i]:
                        opt_forword = opt
                    if opt in self.instructions[j]:
                        opt_backword = opt

                if isinstance(self.instructionAnalysis.latenceSet[opt_forword], dict):
                    if opt_backword in self.instructionAnalysis.latenceSet[opt_forword]:
                        if instructionsSplitList[i][1] in instructionsSplitList[j]:
                            tempIndex = instructionsSplitList[j].index(instructionsSplitList[i][1])
                            judgeIndex = 1
                            if opt_backword == 'fsd':
                                judgeIndex = 0
                            if tempIndex != judgeIndex:
                                self.graphDAG[i][j] = self.instructionAnalysis.latenceSet[opt_forword][opt_backword]

                elif isinstance(self.instructionAnalysis.latenceSet[opt_forword], int):
                    self.graphDAG[i][i] = self.instructionAnalysis.latenceSet[opt_forword]

    def PrintDAG(self, graph):
        for row in graph:
            print(row)

    def PrintScheduledInstructions(self):
        print(self.instructions[0])
        # every instructions
        for currentIst in range(1, len(self.instructions)):
            # every preview instructions
            for previewIst in range(0, currentIst):

                sum = 0
                for temp_column in range(previewIst + 1, currentIst):
                    for temp_row in range(0, currentIst):
                        sum = sum + self.stallTimes[temp_row][temp_column]

                if self.graphDAG[previewIst][currentIst] > currentIst-(previewIst+1) + sum:
                    self.stallTimes[previewIst][currentIst] = self.graphDAG[previewIst][currentIst] - (currentIst - previewIst -1 ) - sum
                    print("Stall\n"*(self.stallTimes[previewIst][currentIst]), end='')
            if self.graphDAG[currentIst-1][currentIst-1] != 0:
                self.stallTimes[currentIst-1][currentIst-1] = self.graphDAG[currentIst-1][currentIst-1]
                print("Stall\n"*(self.stallTimes[currentIst-1][currentIst-1]), end='')
            print(self.instructions[currentIst])
            if currentIst == len(self.instructions) - 1:
                self.stallTimes[currentIst][currentIst] = self.graphDAG[currentIst][currentIst]
                print("Stall\n"*(self.stallTimes[currentIst][currentIst]), end='')






